import type { InfoItem, RemoteCallWpsjsGlobalReturn, WithExecutionWpsjsGlobal } from './types'
import { writeFile } from 'fs/promises'
import path from 'path'

interface Config {
  /**脚本令牌 */
  scriptToken: string
  /**脚本链接 */
  webhookURL: string
  /**异步任务 */
  isAsync?: boolean
  /**在控制台打印日志 */
  printLog?: boolean
  /**在当前路径下写入日志文件 */
  writeLogFile?: boolean
}

const initRemoteCallWpsjsGlobal = (config: Config) => {
  const { scriptToken, webhookURL, isAsync = false, printLog = false, writeLogFile = false, } = config
  let info: InfoItem[] = []
  const handle: ProxyHandler<() => void> = {
    get: (_target, p: string, receiver) => {
      info.push({ method: 'get', arguments: [p] })
      return receiver
    },
    set: (_target, p: string, newValue, receiver) => {
      info.push({ method: 'set', arguments: [p, newValue] })
      return receiver
    },
    apply: (_target, thisArg, argArray) => {
      const lastInfo = info.at(-1)
      if (lastInfo?.arguments[0] === 'execution') {
        info.pop() /* 删除 execution的调用信息 */
        return execution({ scriptToken, webhookURL, isAsync, argv: { info } })
          .then(async (response) => {
            const responseObj = await response.json()
            info = []	/* 执行结束，清空调用 */
            if (printLog) printInfo(responseObj)

            if (writeLogFile) await writeLogFileToCurrent(responseObj)
            return responseObj['data']['result']
          })
      }
      info.push({ method: 'apply', arguments: argArray })
      return thisArg
    },
  }
  return new Proxy(() => { }, handle) as unknown as WithExecutionWpsjsGlobal
}

type ExecutionConfig = Pick<Config, 'scriptToken' | 'webhookURL' | 'isAsync'> & { argv?: Record<string | number, any> }

const execution = ({ scriptToken, webhookURL, isAsync, argv }: ExecutionConfig) => {
  /* 获取请求信息 */
  const data = JSON.stringify({ Context: { argv, } })
  /* 根据是否同步返回不同的url */
  const parsedPath = path.parse(webhookURL)
  parsedPath.base = isAsync ? 'task' : 'sync_task'
  const url = path.format(parsedPath)
  return fetch(url, {
    method: 'post',
    headers: {
      'Content-Type': 'application/json',
      'AirScript-Token': scriptToken
    },
    body: data
  })
}

const queryTask = (id: string) => {
  const url = new URL('https://www.kdocs.cn/api/v3/script/task')
  url.searchParams.append('task_id', id)
  return fetch(url)
}

const printInfo = (remoteCallResponse: RemoteCallWpsjsGlobalReturn) => {
  const responseData = remoteCallResponse as RemoteCallWpsjsGlobalReturn
  const { status, data, error, error_details } = responseData
  console.log('status:', status)
  const time = data.logs.at(-1)!.unix_time - data.logs[1].unix_time
  console.log('runtime:', time)
  if (error) {
    console.error(error_details.name)
    console.error(error_details.msg)
    console.error(error_details.stack)
  }
  const userInfo = data.logs.filter(x => x.filename !== '<system>')
  if (userInfo.length !== 0) {
    console.log('log:')
    for (const item of userInfo) {
      console[item.level](...item.args)
    }
  }
  console.log('result:')
  console.log(data.result)
  return responseData
}

const writeLogFileToCurrent = (data: object) => {
  return writeFile('./wpsjs.log.json', JSON.stringify((data), undefined, 2))
}

export type * from './types'

export {
  execution,
  initRemoteCallWpsjsGlobal,
  queryTask,
  writeLogFileToCurrent,
}
